package com.utils.aes;

import com.google.common.base.Strings;
import com.utils.util.Dates;
import org.apache.commons.lang3.RandomStringUtils;

import static com.utils.util.Dates.Pattern.time_millis;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * AES加密动态 IV 随机规则
 *
 * @author 谢长春 2022-02-09
 */
public enum IvRandomRule {
    alphanumeric("RandomStringUtils.randomAlphanumeric 16位随机【A-Za-z0-9】") {
        @Override
        public byte[] get() {
            return RandomStringUtils.randomAlphanumeric(IV_LENGTH).getBytes(UTF_8);
        }

        @Override
        public void assertIV(final byte[] ivBytes) {
            // 不校验全部是随机值的 IV
        }
    },
    dateAlphanumeric("10位日期(yyyyMMddHH) + 6位随机【A-Za-z0-9】") {
        @Override
        public byte[] get() {
            // Util.encodeBase62(Integer.parseInt(yyyyMMdd.now())) // 如果担心前缀有规律，可以使用 base62 混淆伪装随机值
            return Dates.now().format("yyyyMMddHH").concat(RandomStringUtils.randomAlphanumeric(6)).getBytes(UTF_8);
        }

        @Override
        public void assertIV(final byte[] ivBytes) {
//            final String value = new String(ivBytes, UTF_8);
//            final Integer date = Integer.parseInt(StringUtils.left(value, 10)); // 获取前 10 位日期
//            final Integer now = Integer.parseInt(Dates.now().format("yyyyMMddHH"));
//            final int offset = now - date;
//            Code.A00003.assertHasTrue(offset >= 0 & offset < 100, "动态 IV 前 10 位日期已过期：%s 。 有效期为 24 小时", value);
        }
    },
    timestamp("13位时间戳，前面补0") {
        @Override
        public byte[] get() {
            return Strings.padStart(time_millis.now(), IV_LENGTH, '0').getBytes(UTF_8);
        }

        @Override
        public void assertIV(final byte[] ivBytes) {
//            final String value = new String(ivBytes, UTF_8);
//            final long timestamp = Long.parseLong(value);
//            final long now = Instant.now().toEpochMilli();
//            final long offset = now - timestamp;
//            Code.A00003.assertHasTrue(offset >= 0 && offset < 86400000, "动态 IV 时间戳已过期：%s 。 有效期为 24 小时", value);
        }
    },
    ;
    final String comment;

    IvRandomRule(final String comment) {
        this.comment = comment;
    }

    /**
     * 获取 IV 随机值， 定长 16 位
     *
     * @return byte[]
     */
    public abstract byte[] get();

    /**
     * 断言解密之后的 IV 是否合法，不合法则抛出异常
     *
     * @param ivBytes byte[] 解密之后获得的前 16 位 IV 值
     */
    public abstract void assertIV(final byte[] ivBytes);

    /**
     * 随机生成 IV 长度， 只能固定 16 位
     */
    public static final int IV_LENGTH = 16;
}
